`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: adi
// 
// Create Date: 2021/09/26 15:16:03
// Design Name: 
// Module Name: asyn_fifo_lut
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
//              异步fifo，深度32，宽度4(std fifo)
//              
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

//`define   fwft    1
module asyn_fifo_lut(
    input       wire                asyn_rst,
//-------write
    input       wire                wr_clk  ,
    input       wire                wr_en   ,
    input       wire    [3:0]       din     ,
    output      wire                full    ,
//------read                    
    input       wire                rd_clk  ,
    input       wire                rd_en   ,
    output      reg     [3:0]       dout    ,
    output      wire                empty   
    );
    
    wire    [5:0]       wr_ptr          ;
    wire    [5:0]       wr_ptr_gray     ;
    wire    [5:0]       rd_ptr          ;
    wire    [5:0]       rd_ptr_gray     ; 
    wire                full            ;
    wire                empty           ;
    wire    [3:0]       dout_ram        ;
//-------------ram--------------------- 
       RAM32M #(
      .INIT_A(64'h0000000000000000), // Initial contents of A Port
      .INIT_B(64'h0000000000000000), // Initial contents of B Port
      .INIT_C(64'h0000000000000000), // Initial contents of C Port
      .INIT_D(64'h0000000000000000)  // Initial contents of D Port
   ) RAM32M_inst (
      .DOA      (dout_ram[1:0]      ),     // Read port A 2-bit output
      .DOB      (dout_ram[3:2]      ),     // Read port B 2-bit output
      .DOC      (        ),     // Read port C 2-bit output
      //.DOD      (2'b0    ),     // Read/write port D 2-bit output
      .ADDRA    (rd_ptr[4:0]    ),    // Read port A 5-bit address input
      .ADDRB    (rd_ptr[4:0]    ),    // Read port B 5-bit address input
      .ADDRC    (rd_ptr[4:0]    ),    // Read port C 5-bit address input
      .ADDRD    (wr_ptr[4:0]    ),    // Read/write port D 5-bit address input
      .DIA      (din[1:0]       ),     // RAM 2-bit data write input addressed by ADDRD, read addressed by ADDRA
      .DIB      (din[3:2]       ),     // RAM 2-bit data write input addressed by ADDRD, read addressed by ADDRB
      .DIC      (2'b0           ),     // RAM 2-bit data write input addressed by ADDRD,read addressed by ADDRC
      .DID      (2'b0           ),     // RAM 2-bit data write input addressed by ADDRD, read addressed by ADDRD
      .WCLK     (wr_clk         ),    // Write clock input
      .WE       (wr_en & (~full) )        // Write enable input
   ); 
   
/*
`ifdef vcs
 reg  [3:0]   mem [31:0];
   wire a= wr_en&(~full);
   always @(posedge wr_clk) 
        if(a)
            mem[wr_ptr[4:0]] <= din;
            
    assign dout_ram = mem[rd_ptr[4:0]]; 
`endif*/  
//-----------write   
    asyn_fifo_wr asyn_fifo_wr_u0(
        .clk                (wr_clk         ),                  
        .rst                (asyn_rst       ),
        .full               (full           ),
        .wr_en              (wr_en          ),
        .wr_ptr             (wr_ptr         ),
        .wr_ptr_gray        (wr_ptr_gray    )  
    );    
//----------read
    asyn_fifo_rd asyn_fifo_rd_u0(       
       .clk                 (rd_clk         ),
       .rst                 (asyn_rst       ),
       .empty               (empty          ),
       .rd_en               (rd_en          ),
       .rd_ptr              (rd_ptr         ),
       .rd_ptr_gray         (rd_ptr_gray    )
    );
//-------------同步----------   
    wire    [5:0]   wr_ptr_gray_sync;
    wire    [5:0]   rd_ptr_gray_sync;
    
    xpm_cdc_array_single #(
      .DEST_SYNC_FF(2),   // DECIMAL; range: 2-10
      .INIT_SYNC_FF(0),   // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
      .SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
      .SRC_INPUT_REG(1),  // DECIMAL; 0=do not register input, 1=register input
      .WIDTH(6)           // DECIMAL; range: 1-1024
   )
   xpm_cdc_array_single_u0 (
      .dest_out (wr_ptr_gray_sync   ),  // WIDTH-bit output: src_in synchronized to the destination clock domain. This output is registered.
      .dest_clk (rd_clk             ),  // 1-bit input: Clock signal for the destination clock domain.
      .src_clk  (wr_clk             ),  // 1-bit input: optional; required when SRC_INPUT_REG = 1
      .src_in   (wr_ptr_gray        )   // WIDTH-bit input: Input single-bit array to be synchronized to destination clock
                                        // domain. It is assumed that each bit of the array is unrelated to the others. This
                                        // is reflected in the constraints applied to this macro. To transfer a binary value
                                        // losslessly across the two clock domains, use the XPM_CDC_GRAY macro instead.
   );
    
     xpm_cdc_array_single #(
      .DEST_SYNC_FF(2),   // DECIMAL; range: 2-10
      .INIT_SYNC_FF(0),   // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
      .SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
      .SRC_INPUT_REG(1),  // DECIMAL; 0=do not register input, 1=register input
      .WIDTH(6)           // DECIMAL; range: 1-1024
   )
   xpm_cdc_array_single_u1 (
      .dest_out (rd_ptr_gray_sync   ),  // WIDTH-bit output: src_in synchronized to the destination clock domain. This output is registered.
      .dest_clk (wr_clk             ),  // 1-bit input: Clock signal for the destination clock domain.
      .src_clk  (rd_clk             ),  // 1-bit input: optional; required when SRC_INPUT_REG = 1
      .src_in   (rd_ptr_gray        )   // WIDTH-bit input: Input single-bit array to be synchronized to destination clock
                                        // domain. It is assumed that each bit of the array is unrelated to the others. This
                                        // is reflected in the constraints applied to this macro. To transfer a binary value
                                        // losslessly across the two clock domains, use the XPM_CDC_GRAY macro instead.
   );   
//-------------空满标志判断    
    assign  empty = (wr_ptr_gray_sync == rd_ptr_gray) ? 1'd1 : 1'd0;
    assign  full  = (wr_ptr_gray[5:4] == (~rd_ptr_gray_sync[5:4])) && (wr_ptr_gray[3:0] == rd_ptr_gray_sync[3:0]);
    
    always @(posedge rd_clk) dout <= dout_ram;
        
    
endmodule
